from sklearn.svm._base import BaseLibSVM
from sklearn.svm import OneClassSVM as SklearnOneClassSVM
import numpy as np
import json

class CustomBaseLibSVM(BaseLibSVM):
    @property
    def n_support_(self):
        return getattr(self, '_n_support', None)

    @n_support_.setter
    def n_support_(self, value):
        self._n_support = value

class CustomOneClassSVM(SklearnOneClassSVM, CustomBaseLibSVM):
    def __init__(self, nu=0.5, kernel='rbf', degree=3, gamma='scale', coef0=0.0, tol=1e-3, shrinking=True, 
                 cache_size=200, verbose=False, max_iter=-1):
        super().__init__(nu=nu, kernel=kernel, degree=degree, gamma=gamma, coef0=coef0, tol=tol, 
                         shrinking=shrinking, cache_size=cache_size, verbose=verbose, max_iter=max_iter)

    def fit(self, X, y=None, sample_weight=None):
        super().fit(X, y, sample_weight)
        # 确保 _n_support 被正确设置
        self._n_support = self.n_support_

def serialize_oneclasssvm(model):
    """将 OneClassSVM 模型序列化为字典"""
    return {
        'meta': 'OneClassSVM',
        'params': model.get_params(),
        'attributes': {
            'support_': model.support_.tolist(),
            'support_vectors_': model.support_vectors_.tolist(),
            'dual_coef_': model.dual_coef_.tolist(),
            'intercept_': model.intercept_.tolist(),
            'n_support_': model.n_support_.tolist(),
            'offset_': model.offset_.tolist(),
            'shape_fit_': model.shape_fit_,
            '_sparse': model._sparse,  # 添加 _sparse 属性
            '_dual_coef_': model._dual_coef_.tolist(),  # 添加 _dual_coef_ 属性
            '_intercept_': model._intercept_.tolist()  # 添加 _intercept_ 属性
        }
    }

def deserialize_oneclasssvm(model_dict):
    """将字典反序列化为 OneClassSVM 模型"""
    model = CustomOneClassSVM(**model_dict['params'])
    attrs = model_dict['attributes']
    
    # 确保所有属性都被正确设置
    model.support_ = np.array(attrs['support_'])
    model.support_vectors_ = np.array(attrs['support_vectors_'])
    model.dual_coef_ = np.array(attrs['dual_coef_'])
    model.intercept_ = np.array(attrs['intercept_'])
    model.offset_ = np.array(attrs['offset_'])
    model.shape_fit_ = attrs['shape_fit_']
    
    # 根据 support_vectors_ 的类型设置 _sparse 属性
    model._sparse = attrs['_sparse']
    
    # 确保 n_support_ 被正确设置
    model._n_support = np.array(attrs['n_support_'])
    
    # 确保 _dual_coef_ 和 _intercept_ 被正确设置
    model._dual_coef_ = np.array(attrs['_dual_coef_'])
    model._intercept_ = np.array(attrs['_intercept_'])
    
    # 重要：确保模型的内部状态一致
    model._validate_for_predict(model.support_vectors_)
    
    return model

if __name__ == '__main__':
    # 训练数据
    X = np.array([[1, 1], [2, 2], [3, 3], [4, 4], [5, 5], [10, 10], [11, 11], [12, 12]])
    oc_svm = CustomOneClassSVM(nu=0.1, kernel='rbf', gamma=0.1)
    oc_svm.fit(X)

    # 序列化模型为 JSON 文件
    model_dict = serialize_oneclasssvm(oc_svm)
    with open('oc_svm.json', 'w') as f:
        json.dump(model_dict, f)

    # 反序列化模型
    with open('oc_svm.json', 'r') as f:
        loaded_model_dict = json.load(f)
    loaded_oc_svm = deserialize_oneclasssvm(loaded_model_dict)

    # 预测新数据
    X_test = np.array([[1, 1], [3, 3], [11, 11], [13, 13]])
    try:
        y_pred = loaded_oc_svm.predict(X_test)
        print("预测结果:", y_pred)
    except ValueError as e:
        print("预测时出错:", e)